import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.Socket;
import java.net.UnknownHostException;

public class Client extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTextField textFieldIP;
	private JTextField textFieldPort;
	private JButton btnConnect;
	private JTextArea textAreaQueryString;
	private JTable tableResult;
	private boolean isConecting;
	private JLabel lblNotConnected;
	private DefaultTableModel tableResultModel;
	ObjectInputStream objectInput;
	ObjectOutputStream objectOutput;

	Socket server;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Client frame = new Client();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Client() {
		setResizable(false);
		isConecting = false;
		setTitle("Cliet");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 649, 380);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		JLabel lblIp = new JLabel("IP:");

		textFieldIP = new JTextField();
		textFieldIP.setText("127.0.0.1");
		textFieldIP.setColumns(10);

		JLabel lblPort = new JLabel("Port:");

		textFieldPort = new JTextField();
		textFieldPort.setText("8888");
		textFieldPort.setColumns(10);

		btnConnect = new JButton("Connect");
		btnConnect.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {

				int port = -1;
				try {
					port = Integer.parseInt(textFieldPort.getText());
					if (port < 1 || port > 9999) {
						JOptionPane.showMessageDialog(contentPane,
								"Port must be beween 1 ~ 9999");
						return;
					}
				} catch (NumberFormatException nfe) {
					JOptionPane.showMessageDialog(contentPane,
							"Port must be a number");
					return;
				}
				connect(textFieldIP.getText(), port);

			}
		});

		JLabel lblStatus = new JLabel("Status:");

		lblNotConnected = new JLabel("Not connected.");

		JLabel lblQuerry = new JLabel("Query string:");

		JScrollPane scrollPane = new JScrollPane();

		JScrollPane scrollPane_1 = new JScrollPane();

		JButton btnExecute = new JButton("Execute");
		btnExecute.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if (isConecting) {
					String sqlString = textAreaQueryString.getText()
							.replaceAll("\n", " ").trim();
					String[] strs = sqlString.split(";");

					for (String sqlStr : strs) {
						DTO dto = Exec(sqlStr);
						if (dto != null) {
							JOptionPane.showMessageDialog(contentPane,
									dto.messenger);
						}
					}
				}

			}
		});
		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane
				.setHorizontalGroup(gl_contentPane
						.createParallelGroup(Alignment.LEADING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addContainerGap()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.LEADING)
														.addComponent(
																scrollPane_1,
																GroupLayout.DEFAULT_SIZE,
																501,
																Short.MAX_VALUE)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addGroup(
																				gl_contentPane
																						.createParallelGroup(
																								Alignment.LEADING,
																								false)
																						.addGroup(
																								gl_contentPane
																										.createSequentialGroup()
																										.addComponent(
																												lblIp)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												textFieldIP,
																												GroupLayout.PREFERRED_SIZE,
																												GroupLayout.DEFAULT_SIZE,
																												GroupLayout.PREFERRED_SIZE)
																										.addGap(18)
																										.addComponent(
																												lblPort)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												textFieldPort,
																												GroupLayout.PREFERRED_SIZE,
																												33,
																												GroupLayout.PREFERRED_SIZE)
																										.addGap(18)
																										.addComponent(
																												btnConnect)
																										.addGap(18)
																										.addComponent(
																												lblStatus)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												lblNotConnected))
																						.addGroup(
																								gl_contentPane
																										.createSequentialGroup()
																										.addComponent(
																												lblQuerry)
																										.addPreferredGap(
																												ComponentPlacement.RELATED)
																										.addComponent(
																												scrollPane)))
																		.addPreferredGap(
																				ComponentPlacement.RELATED)
																		.addComponent(
																				btnExecute)))
										.addContainerGap()));
		gl_contentPane
				.setVerticalGroup(gl_contentPane
						.createParallelGroup(Alignment.LEADING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addContainerGap()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.BASELINE)
														.addComponent(lblIp)
														.addComponent(
																textFieldIP,
																GroupLayout.PREFERRED_SIZE,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.PREFERRED_SIZE)
														.addComponent(lblPort)
														.addComponent(
																textFieldPort,
																GroupLayout.PREFERRED_SIZE,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.PREFERRED_SIZE)
														.addComponent(
																btnConnect)
														.addComponent(lblStatus)
														.addComponent(
																lblNotConnected))
										.addPreferredGap(
												ComponentPlacement.UNRELATED)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.LEADING,
																false)
														.addComponent(lblQuerry)
														.addComponent(
																scrollPane,
																GroupLayout.DEFAULT_SIZE,
																62,
																Short.MAX_VALUE)
														.addComponent(
																btnExecute,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.DEFAULT_SIZE,
																Short.MAX_VALUE))
										.addGap(21)
										.addComponent(scrollPane_1,
												GroupLayout.DEFAULT_SIZE, 146,
												Short.MAX_VALUE)
										.addContainerGap()));

		tableResult = new JTable();

		tableResultModel = new DefaultTableModel();

		tableResult.setModel(tableResultModel);

		scrollPane_1.setViewportView(tableResult);

		textAreaQueryString = new JTextArea();
		scrollPane.setViewportView(textAreaQueryString);
		contentPane.setLayout(gl_contentPane);
	}

	private DTO Exec(String sqlString) {
		try {
			if (sqlString == null || sqlString.length() == 0)
				return DTO.CreateDTO("Empty String");

			objectOutput.writeObject(sqlString);
			DTO dto = (DTO) (objectInput.readObject());
			if (dto.messenger.equals("Disconnected!")) {
				isConecting = false;
				lblNotConnected.setText("Not connected.");
				btnConnect.setEnabled(true);
			} else {
				UpdateGUI(dto);
			}
			return dto;
		} catch (Exception e1) {
			e1.printStackTrace();
			isConecting = false;
			lblNotConnected.setText("Not connected.");
			btnConnect.setEnabled(true);
			return null;
		}

	}

	private void connect(String textIP, int port) {

		try {

			server = new Socket(textIP, port);

			objectInput = new ObjectInputStream(server.getInputStream());
			objectOutput = new ObjectOutputStream(server.getOutputStream());

			isConecting = true;
			lblNotConnected.setText("Conected");
			btnConnect.setEnabled(false);
			textFieldIP.setEditable(false);
			textFieldPort.setEditable(false);
		} catch (ConnectException e1) {
			JOptionPane.showMessageDialog(contentPane,
					"Cannot connect to server.");
			e1.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			JOptionPane.showMessageDialog(contentPane, "Unknow host.");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void UpdateGUI(DTO input) {
		if (input.getfieldNames() != null || input.getData() != null) {
			this.tableResultModel = new DefaultTableModel(input.getData(),
					input.getfieldNames());
			this.tableResult.setModel(tableResultModel);
		}
	}
}
